package com.lyl.service.impl;

import com.lyl.constant.LoginConstant;
import com.sun.org.apache.bcel.internal.generic.ATHROW;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.security.auth.login.LoginContext;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lylbell
 * @date 2021-06-17 22:41
 */
@Service
public class UserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        ServletRequestAttributes request = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        String loginType = request.getRequest().getParameter("login_type");//用于区分是管理员还是用户会员
        if (StringUtils.isEmpty(loginType)) {
            throw new AuthenticationServiceException("登录类型不能为空");
        }
        //要使refresh_token生成token生效，必须在添加第三方客户端那边添加一个grant_type为refresh_token
        //采用refresh_token去生成token，需要将refresh_token中存储的用户名（实际上是id）转化成username。

        String grant_type = request.getRequest().getParameter("grant_type");
        if (LoginConstant.REFRESH_TOKEN.equals(grant_type.toUpperCase())) {
            username = adjustUsername(username,loginType);
        }

        UserDetails userDetails = null;

        try {
            switch(loginType) {
                case LoginConstant.ADMIN_TYPE:
                    userDetails = loadAdminUserByUsername(username);
                    break;
                case LoginConstant.MEMBER_TYPE:
                    userDetails = loadMemberUserByUsername(username);
                    break;
                default:
                    throw new AuthenticationServiceException("暂不支持的登录方式"+loginType);
            }
        } catch (AuthenticationServiceException e) {
            throw new UsernameNotFoundException("用户名"+username+"不存在");
        }

        return userDetails;
    }

    private String adjustUsername(String username, String loginType) {
        if (LoginConstant.ADMIN_TYPE.equals(loginType)) {
            return jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_USER_WITH_ID,String.class,username);
        }
        if (LoginConstant.MEMBER_TYPE.equals(loginType)) {
            return jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_USER_WITH_ID,String.class,username);
        }
        return username;
    }


    /**
     * 会员登录处理
     * @param username
     * @return
     */
    private UserDetails loadMemberUserByUsername(String username) {
        return jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_SQL, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int i) throws SQLException {
                if (rs.wasNull()) {
                    throw new UsernameNotFoundException("用户名"+username + "不存在");
                }
                long id = rs.getLong("id");
                String password = rs.getString("password");
                int status = rs.getInt("status");
                //会员用户没有权限，给一个默认的
                return new User(String.valueOf(id),password,status == 1,true,true,true, Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
            }
        },username,username);
    }

    /**
     * 管理员登录处理
     * @param username
     * @return
     */
    private UserDetails loadAdminUserByUsername(String username) {
        //1、使用用户名查询用户
        //3、封装成一个UserDetail对象，返回
       return jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_SQL, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                if (rs.wasNull()) {
                    throw new UsernameNotFoundException("用户名"+username + "不存在");
                }
                long id = rs.getLong("id");
                String password = rs.getString("password");
                int status = rs.getInt("status");
                return new User(String.valueOf(id),password,status == 1,true,true,true,getSysUserPermission(id));
            }
        },username);


    }

    /**2、查询这个用户对应的权限
     * 获取用户权限
     * @param id
     * @return
     */
    private Collection<? extends GrantedAuthority> getSysUserPermission(long id) {
        //1、当用户为超级管理员时，拥有全部权限
        String role = jdbcTemplate.queryForObject(LoginConstant.QUERY_ROLE_CODE_SQL, String.class, id);
        List<String> permissions = null;
        if (LoginConstant.ADMIN_ROLE_CODE.equals(role)) {
            permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_ALL_PERMISSIONS,String.class);
        }else {//2、普通用户，查询权限
            permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_PERMISSION_SQL,String.class,id);
        }
        if (permissions == null ||permissions.isEmpty()) {
            return Collections.emptySet();
        }
        return permissions.stream().distinct() //去重
                .map(perm->new SimpleGrantedAuthority(perm)).collect(Collectors.toSet());
    }
}
